from datetime import datetime, timedelta

from info import db
from info.constants import ADMIN_USER_PAGE_MAX_COUNT, QINIU_DOMIN_PREFIX
from info.utils.response_code import RET, error_map
from . import admin_blu
import time
from flask import request, session, redirect, url_for, render_template, current_app, g, abort, jsonify
from info.common import user_login_data, img_upload
from info.models import User, Category, News


# 登陆页面
@admin_blu.route('/login', methods=['GET', "POST"])
def login():
    if request.method == "GET":
        user_id = session.get("user_id")
        is_admin = session.get("is_admin")
        # 判断是否有session记录，进行页面跳转
        if user_id and is_admin:
            return redirect(url_for("admin.index"))
        else:
            return render_template("admin/login.html")

    # post请求登陆
    username = request.form.get("username")
    password = request.form.get("password")

    # 校验参数
    if not all([username, password]):
        return render_template("admin/login.html", errmsg="参数不完整")

    # 查询出user对象
    try:
        user = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except BaseException as e:
        current_app.logger.error(e)
        return render_template("admin/login.html", errmsg="数据库错误")

    # 判断用户是否存在
    if not user:
        return render_template("admin/login.html", errmsg="您非管理员用户")

    # 校验密码
    if not user.check_password(password):
        return render_template("admin/login.html", errmsg="密码/账号错误")

    # session记录状态信息
    session["user_id"] = user.id
    session["is_admin"] = True

    return redirect(url_for("admin.index"))


# 后台首页
@admin_blu.route('/index')
@user_login_data
def index():
    return render_template("admin/index.html", user=g.user.to_dict())


# 退出登陆逻辑
@admin_blu.route('/logout')
def logout():
    session.pop("user_id", None)
    session.pop("is_admin", None)
    return redirect(url_for("home.index"))


# 用户统计
@admin_blu.route('/user_count')
def user_count():
    # 用户总数
    total_count = 0
    try:
        total_count = User.query.filter(User.is_admin != True).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 月新增人数
    mon_count = 0
    # 获取当前 年 和 月
    t = time.localtime()
    #  构建时间字符串
    y_m_str = "%d-%02d-01" % (t.tm_year, t.tm_mon)  # 当月注册用户，就是从这个月一号开始的
    # 转为的datatime对象
    Y_m = datetime.strptime(y_m_str, "%Y-%m-%d")

    # 查找当月注册用户数量
    try:
        mon_count = User.query.filter(User.create_time >= Y_m, User.is_admin != True).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 日新增人数
    day_count = 0
    # 获取当前 年 和 月
    t = time.localtime()
    #  构建时间字符串
    y_m_str = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday)  # 当天注册用户，就是从当天时间开始的
    # 转为的datatime对象
    Y_m = datetime.strptime(y_m_str, "%Y-%m-%d")

    # 查找当天注册用户数量
    try:
        mon_count = User.query.filter(User.create_time >= Y_m, User.is_admin != True).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 折线图
    active_count = []  # 数量列表
    active_time = []  # 时间列表
    # 获取 前三十天每天的注册用户数量 和 前三十天的时间列表
    for i in range(30):
        start_time = Y_m - timedelta(days=i)
        end_time = Y_m + timedelta(days=1 - i)

        try:
            a_count = User.query.filter(User.is_admin == False, User.create_time >= start_time,
                                        User.create_time <= end_time).count()
            active_count.append(a_count)
            # 日期对象 转为 日期字符串
            one_day_str = start_time.strftime("%Y-%m-%d")
            active_time.append(one_day_str)
        except BaseException as e:
            current_app.logger.error(e)

    active_count.reverse()
    active_time.reverse()
    data = {
        "total_count": total_count,
        "mon_count": mon_count,
        "day_count": day_count,
        "active_count": active_count,
        "active_time": active_time
    }
    return render_template("admin/user_count.html", data=data)


# 显示用户列表
@admin_blu.route('/user_list')
def user_list():
    # 获取当前页码
    p = request.args.get("p", 1)
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    user_list = list()
    cur_page = 1
    total_page = 1
    try:
        pn = User.query.filter(User.is_admin == False).paginate(p, ADMIN_USER_PAGE_MAX_COUNT)
        cur_page = pn.page
        total_page = pn.pages
        user_list = [user.to_admin_dict() for user in pn.items]

    except BaseException as e:
        current_app.logger.error(e)

    data = {
        "user_list": user_list,
        "cur_page": cur_page,
        "total_page": total_page
    }
    # 后端渲染收藏的新闻
    return render_template("admin/user_list.html", data=data)


# 修改分类信息
@admin_blu.route('/news_type', methods=['GET', 'POST'])
def news_type():
    if request.method == "GET":
        # 查找新闻分类列表进行渲染
        categories = []
        try:
            categories = Category.query.filter(Category.id != 1).all()
        except BaseException as e:
            current_app.logger.error(e)

        return render_template("admin/news_type.html", categories=categories)

    # POST处理
    id = request.json.get("id")
    name = request.json.get("name")
    if not name:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if id:  # 如果是修改
        try:
            id = int(id)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

        # 修改的分类对象
        try:
            category = Category.query.get(id)
            category.name = name
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])
    else:  # 如果是新增
        try:
            category = Category()
            category.name = name
            db.session.add(category)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 显示新闻审核列表
@admin_blu.route('/news_review')
def news_review():
    # 获取当前页码
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")

    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    news_list = []
    cur_page = 1
    total_page = 1

    filter_list = []
    if keyword:  # 如果进行了搜索过滤
        filter_list.append(News.title.contains(keyword))

    # 查询新闻审核列表
    try:
        pn = News.query.filter(*filter_list).order_by(News.status.desc(), News.create_time.desc()).paginate(p,
                                                                                                            ADMIN_USER_PAGE_MAX_COUNT)
        news_list = [news.to_review_dict() for news in pn.items]
        cur_page = pn.page
        total_page = pn.pages
    except BaseException as e:
        current_app.logger.error(e)

    data = {
        "news_list": news_list,
        "cur_page": cur_page,
        "total_page": total_page
    }
    return render_template("admin/news_review.html", data=data)


# 显示新闻审核详情
@admin_blu.route('/news_review_detail/<int:news_id>')
def news_review_detail(news_id):
    # 根据新闻id取出新闻模型
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        abort(404)

    return render_template("admin/news_review_detail.html", news=news.to_dict())


# 提交审核
@admin_blu.route('/news_review_action', methods=['POST'])
def news_review_action():
    # 获取参数
    news_id = request.json.get("news_id")
    action = request.json.get("action")
    reason = request.json.get("reason")
    # 校验参数
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if action not in ["accept", "reject"]:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 查询新闻对象模型
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    # 未通过
    if action == "reject":
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg="请输入未通过原因")
        try:
            news.status = -1
            news.reason = reason
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    else:
        try:
            news.status = 0
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 显示新闻编辑列表
@admin_blu.route('/news_edit')
def news_edit():
    # 获取当前页码
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")

    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    news_list = []
    cur_page = 1
    total_page = 1

    filter_list = []
    if keyword:  # 如果进行了搜索过滤
        filter_list.append(News.title.contains(keyword))

    # 查询新闻审核列表
    try:
        pn = News.query.filter(*filter_list).order_by(News.create_time.desc()).paginate(p,
                                                                                        ADMIN_USER_PAGE_MAX_COUNT)
        news_list = [news.to_review_dict() for news in pn.items]
        cur_page = pn.page
        total_page = pn.pages
    except BaseException as e:
        current_app.logger.error(e)

    data = {
        "news_list": news_list,
        "cur_page": cur_page,
        "total_page": total_page
    }
    return render_template("admin/news_edit.html", data=data)


# 显示新闻编辑详情
@admin_blu.route('/news_edit_detail/<int:news_id>')
def news_edit_detail(news_id):
    # 根据新闻id取出新闻模型
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(404)

    # 查找分类列表
    categories = []
    try:
        categories = Category.query.filter(Category.id != 1).all()
    except BaseException as e:
        current_app.logger.error(e)

    category_list = []
    for category in categories:
        category_dict = category.to_dict()
        is_selected = False
        if category.id == news.category_id:
            is_selected = True

        category_dict["is_selected"] = is_selected
        category_list.append(category_dict)

    return render_template("admin/news_edit_detail.html", news=news.to_dict(), category_list=category_list)


# 新闻编辑
@admin_blu.route('/news_edit_detail', methods=['POST'])
def news_edit_action():
    # 获取参数
    news_id = request.form.get("news_id")
    category_id = request.form.get("category_id")
    title = request.form.get("title")
    digest = request.form.get("digest")
    content = request.form.get("content")
    index_image = request.files.get("index_image")
    # 校验参数
    if not all([news_id, category_id, title, digest, content]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        news_id = int(news_id)
        category_id = int(category_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 查询新闻对象
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    if index_image:
        try:
            img_bytes = index_image.read()
            file_name = img_upload(img_bytes)
            news.index_image_url = QINIU_DOMIN_PREFIX + file_name
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 修改数据
    news.title = title
    news.digest = digest
    news.category_id = category_id
    news.content = content

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])
